#include "typedef.h"
#include "asm/includes.h"

#ifdef CONFIG_RELEASE_ENABLE
#define     INTERRUPT_MODE          0
#else
#define     INTERRUPT_MODE          1
#endif

#define WDTEN		4
#define WDTMD 		5
#define WDTCLR		6
#define	WDTINT		7

static const u32 wdt_time[] = {
    1,    2,     4,     8,
    16,   32,    64,   128,
    256,  512,  1024,  2048,
    4096, 8192, 16384, 32768,
};

void wdt_tx_con(u8 data)
{
    p33_tx_1byte(P3_WDT_CON, data);
}

void wdt_or_con(u8 data)
{
    p33_or_1byte(P3_WDT_CON, data);
}

void wdt_and_con(u8 data)
{
    p33_and_1byte(P3_WDT_CON, data);
}

u8 wdt_rx_con(void)
{
    return p33_rx_1byte(P3_WDT_CON);
}



void wdt_close(void)
{
    wdt_tx_con(0);
}


void wdt_enable(void)
{
    wdt_or_con((u8)BIT(WDTEN));
}

void wdt_disable(void)
{
    wdt_and_con((u8)~BIT(WDTEN));
}

void wdt_clear(void)
{
    wdt_or_con((u8)BIT(WDTCLR));
}

void clr_wdt(void)
{
    wdt_clear();
}

void wdt_set_irq(void *handler)
{
    /* request_irq(IRQ_RTC_WDT_IDX, 3, handler, 0); */
    wdt_or_con((u8)BIT(WDTMD));
    wdt_or_con((u8)BIT(WDTCLR));
    wdt_enable();
    JL_P33->RTC_CON |= BIT(4);
}

void wdt_clr_pending(void)
{
    wdt_clear();
}

void trace_call_stack();
void wdt_isr(void)
{
    u32 tmp;
    u32 rets, reti;


    //trace_call_stack();
    __asm__ volatile("%0 = rets" : "=r"(rets));
    __asm__ volatile("%0 = reti" : "=r"(reti));

    printf("\r\n\r\n---------------------------watchdog---------------------\r\n\r\n");
    printf("RETS = %08x \r\n", rets);
    printf("RETI = %08x \r\n", reti);

    __asm__ volatile("%0 = sp" : "=r"(tmp));
    printf("SP = %08x \r\n", tmp);
    __asm__ volatile("%0 = usp" : "=r"(tmp));
    printf("USP = %08x \r\n", tmp);
    __asm__ volatile("%0 = ssp" : "=r"(tmp));
    printf("SSP = %08x \r\n", tmp);
    while (1);
}


void wdt_init(u8 time)
{
#if(INTERRUPT_MODE)
    wdt_tx_con(0);
    wdt_tx_con(time & 0x0F);
    wdt_set_irq(wdt_isr);
    WDT_EXPT_EN(1);
#else
    wdt_and_con((u8)~BIT(WDTEN));
    wdt_tx_con(0);
    wdt_tx_con(time & 0x0F);
    wdt_or_con((u8)BIT(WDTEN));
#endif
}

u32 wdt_get_time(void)
{
    u8 wdt_con = wdt_rx_con();
    if (wdt_con & BIT(WDTEN)) {
        wdt_clear();
        return wdt_time[wdt_con & 0x0f];
    }
    return 0;
}


